﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using FinancePortal.Business.Infraestructure;
using FinancePortal.Business.Repository;
using FinancePortal.Domain.Enum;
using FinancePortal.Domain.Model;
using FinancePortal.Web.Model;

namespace FinancePortal.Controllers
{
    [Permission(Roles = "Worker, Administrator, Client")]
    public class CalendarController : Controller
    {
        #region Repositories

        private readonly IActivityRepository _activityRepository;
        private readonly IActivityScheduleRepository _activityResourceRepository;
        private readonly IAreaRepository _areaRepository;
        private readonly IResourceRepository _resourceRepository;
        private readonly IVacationScheduleRepository _vacationScheduleRepository;

        #endregion

        public CalendarController(IActivityRepository activityRepository,
            IActivityScheduleRepository activityResourceRepository, IResourceRepository resourceRepository,
            IVacationScheduleRepository vacationScheduleRepository, IAreaRepository areaRepository)
        {
            _activityRepository = activityRepository;
            _activityResourceRepository = activityResourceRepository;
            _areaRepository = areaRepository;
            _resourceRepository = resourceRepository;
            _vacationScheduleRepository = vacationScheduleRepository;
        }

        #region Helpers

        private static DateTime ConvertFromUnixTimestamp(double timestamp)
        {
            var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return origin.AddSeconds(timestamp);
        }

        private static double ConvertToUnixTimestamp(DateTime date)
        {
            var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            var diff = date - origin;
            return Math.Floor(diff.TotalSeconds);
        }

        #endregion

        #region Common

        public ActionResult Index()
        {
            var areaList = _areaRepository.GetAll().Select(i =>
                new SelectListItem { Text = i.Name, Value = i.Id.ToString() }).ToList();
            areaList.Insert(0, new SelectListItem { Text = "All", Value = "" });
            ViewBag.Areas = areaList;

            return View();
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public JsonResult GetResourcesList(string id)
        {
            var activity = _activityRepository.GetById(Int32.Parse(id));
            var listResource = (from r in _resourceRepository.GetAll()
                                where r.AreaId == activity.AreaId
                                    && r.Profile != (int)Profile.Client
                                orderby r.Name
                                select new SelectListItem
                                {
                                    Value = r.Id.ToString(),
                                    Text = r.Name
                                }).ToList();

            return Json(listResource, JsonRequestBehavior.AllowGet);
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public JsonResult GetResourcesListByArea(string id)
        {
            //var idArea = _resourceRepository.GetBySOEID(ResourceManagement.GetSOEID(HttpContext)).AreaId;
            var listResource = (from r in _resourceRepository.GetByArea(Int32.Parse(id))
                                orderby r.Name
                                select new SelectListItem
                                {
                                    Value = r.Id.ToString(),
                                    Text = r.Name
                                }).ToList();

            return Json(listResource, JsonRequestBehavior.AllowGet);
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public JsonResult GetClientList(string id)
        {
            var activity = _activityRepository.GetById(Int32.Parse(id));
            var listResource = (from r in _resourceRepository.GetAll()
                                where r.AreaId == activity.AreaId
                                    && r.Profile == (int)Profile.Client
                                orderby r.Name
                                select new SelectListItem
                                {
                                    Value = r.Id.ToString(),
                                    Text = r.Name
                                }).ToList();

            return Json(listResource, JsonRequestBehavior.AllowGet);
        }

        #endregion

        #region ActivitySchedule

        [Permission(Roles = "Administrator")]
        public ActionResult ActivityManagement()
        {
            var resource = _resourceRepository.GetBySOEID(ResourceManagement.GetSOEID(this.Request));
            var listActivity = _activityRepository.GetByArea(resource.AreaId).Select(a =>
                    new
                    {
                        Id = a.Id,
                        Name = a.Name
                    }).ToList();
            listActivity.Insert(0, new { Id = 0, Name = "" });

            //var listClients = _resourceRepository.GetAll().Where(c => c.Profile == (int)Profile.Client).
            //    OrderBy(c => c.Name);

            var listClients = _areaRepository.GetAll().Where(a => a.AreaClient == true).
                OrderBy(c => c.Name);

            ViewBag.ActivityId = new SelectList(listActivity, "Id", "Name");
            ViewBag.Clients = new SelectList(listClients, "Id", "Name");
            return View(resource);
        }

        public JsonResult ListActivities(double start, double end, string filter)
        {
            var fromDate = ConvertFromUnixTimestamp(start);
            var toDate = ConvertFromUnixTimestamp(end);
            var resource = _resourceRepository.GetBySOEID(ResourceManagement.GetSOEID(this.Request));

            var list = _activityResourceRepository.GetByResource(resource.Id,
                fromDate, toDate);

            var returnList = from l in list
                             select new
                             {
                                 id = l.Id,
                                 title = l.Activity.Name,
                                 start = l.FromDate.ToString("s"),
                                 end = l.ToDate.ToString("s"),
                                 completed = l.Completed,
                                 type = "activity",
                                 isAdm = resource.Profile == (int)Profile.Administrator,
                                 backgroundColor = ReturnImage(l.Completed, l.ToDate.Date, l.ToDate.AddDays(-l.WarningDays)),
                                 allDay = false
                             };

            return Json(returnList.ToArray(), JsonRequestBehavior.AllowGet);
        }

        private object ReturnImage(bool completed, DateTime fromDate, DateTime warningDate)
        {
            string img;

            if (completed)
                img = String.Empty; //Url.Content("~/Content/images/thumb-ok.png");
            else if (warningDate > DateTime.Now.Date)
                img = "#00AF33"; //Url.Content("~/Content/images/thumb-green.png");
            else if (warningDate >= DateTime.Now.Date || fromDate >= DateTime.Now.Date)
                img = "#FFC125"; // Url.Content("~/Content/images/thumb-yellow.png");
            else
                img = "#CC1100"; // Url.Content("~/Content/images/thumb-red.png");

            return img;
        }

        [Transactional, Permission(Roles = "Administrator")]
        public ActionResult AddActivity(int activityId, long dateStamp, int fromHours, int fromMinutes, int toHours,
            int toMinutes, int warning, string resources, string clients)
        {
            var date = ConvertFromUnixTimestamp(dateStamp).Date;
            var fromDate = date.AddHours(fromHours).AddMinutes(fromMinutes);
            var toDate = date.AddHours(toHours).AddHours(2); 
            var listResource = new List<Resource>();
            var listArea = new List<Area>();

            new List<String>(resources.Split(new[] { ',' })).ForEach(item =>
            {
                listResource.Add(_resourceRepository.GetById(Int32.Parse(item)));
            });

            if (!String.IsNullOrEmpty(clients))
            {
                new List<String>(clients.Split(new[] { ',' })).ForEach(item =>
                {
                    listArea.Add(_areaRepository.GetById(Int32.Parse(item)));
                });
            }

            var ar = new ActivitySchedule
            {
                ActivityId = activityId,
                OwnerId = _resourceRepository.GetBySOEID(ResourceManagement.GetSOEID(this.Request)).Id,
                FromDate = fromDate,
                ToDate = toDate,
                RegisterDate = DateTime.Now,
                Participants = listResource,
                AreasClient = listArea,
                Completed = false,
                WarningDays = warning
            };

            _activityResourceRepository.Save(ar);

            return null;
        }

        [Transactional]
        [Permission(Roles = "Administrator")]
        public ActionResult DeleteActivity(int activityId)
        {
            var ar = _activityResourceRepository.GetById(activityId);
            _activityResourceRepository.Delete(ar);

            return null;
        }

        public ActionResult ActivityModal(int id)
        {
            var ac = _activityResourceRepository.GetById(id);
            return PartialView("_ActivityModal", ac);
        }

        [HttpPost]
        [Transactional]
        public ActionResult ActivityModalPost(int id) //, FormCollection collection)
        {
            var ac = _activityResourceRepository.GetById(id);
            ac.Completed = true;
            _activityResourceRepository.Save(ac);

            return null;
        }

        public ActionResult ActivityModalDelete(int id)
        {
            var ac = _activityResourceRepository.GetById(id);
            return PartialView("_ActivityModalDelete", ac);
        }

        [HttpPost]
        [Transactional]
        public ActionResult ActivityModalDeletePost(int id)//, FormCollection collection)
        {
            var ac = _activityResourceRepository.GetById(id);
            _activityResourceRepository.Delete(ac);

            return null;
        }

        [HttpPost]
        [Transactional]
        [Permission(Roles = "Administrator")]
        public ActionResult ActivityModalUncomplete(int id, FormCollection collection)
        {
            var ac = _activityResourceRepository.GetById(id);
            ac.Completed = false;
            _activityResourceRepository.Save(ac);

            return null;
        }

        #endregion

        #region Vacation Schedule

        public ActionResult VacationModalDelete(int id)
        {
            var vc = _vacationScheduleRepository.GetById(id);
            return PartialView("_VacationModalDelete", vc);
        }

        [HttpPost]
        [Transactional]
        public ActionResult VacationModalDeletePost(int id)
        {
            var vc = _vacationScheduleRepository.GetById(id);
            _vacationScheduleRepository.Delete(vc);

            return null;
        }

        public JsonResult ListVacations(double start, double end, string filter)
        {
            var fromDate = ConvertFromUnixTimestamp(start);
            var toDate = ConvertFromUnixTimestamp(end);
            var resource = _resourceRepository.GetBySOEID(ResourceManagement.GetSOEID(this.Request));

            IList<VacationSchedule> list;

            if (String.IsNullOrEmpty(filter))
                list = _vacationScheduleRepository.GetAll().ToList();
            else
                list = _vacationScheduleRepository.GetByArea(Int32.Parse(filter));

            var returnList = from l in list
                             select new
                             {
                                 id = l.Id,
                                 title = l.Resource.Name,
                                 start = l.FromDate.ToString("s"),
                                 end = EndVacation(l.ToDate),
                                 completed = l.FromDate.Date < DateTime.Now.Date,
                                 type = "vacation",
                                 isAdm = IsVacationAdmin(resource, l),
                                 backgroundColor = l.ResourceId == resource.Id ? "#00AF33" : String.Empty,
                                 allDay = true
                             };

            return Json(returnList.ToArray(), JsonRequestBehavior.AllowGet);
        }

        private static bool IsVacationAdmin(Resource resource, VacationSchedule schedule)
        {
            return (resource.Profile == (int)Profile.Administrator &&
                (!resource.Area.ParentAreaId.HasValue || resource.AreaId == schedule.Resource.AreaId) ||
                schedule.ResourceId == resource.Id);
        }

        private string EndVacation(DateTime dateTime)
        {
            if (dateTime.DayOfWeek == DayOfWeek.Saturday)
                dateTime.AddDays(1);

            return dateTime.ToString("s");
        }

        [Permission(Roles = "Worker, Administrator")]
        public ActionResult VacationManagement()
        {
            //var lisArea = _areaRepository.GetByResource(ResourceManagement.GetAreas(HttpContext));
            var idArea = _resourceRepository.GetBySOEID(ResourceManagement.GetSOEID(this.Request)).AreaId;
            var listArea = _areaRepository.GetByResource(idArea)
                .Select(a =>
                    new
                    {
                        Id = a.Id,
                        Name = a.Name
                    }).ToList();
            listArea.Insert(0, new { Id = 0, Name = "" });

            var listDeputy = _resourceRepository.GetAll().OrderBy(r => r.Name)
                .Where(r => r.Profile != (int)Profile.Client).Select(a =>
                    new
                    {
                        Id = a.Id,
                        Name = a.Name
                    }).ToList();

            ViewBag.AreaId = new SelectList(listArea, "Id", "Name");
            ViewBag.DeputyList = new SelectList(listDeputy, "Id", "Name");

            return View();
        }

        [Transactional, Permission(Roles = "Worker, Administrator")]
        public ActionResult AddVacation(int resourceId, long initialDateStamp, int totalDays, int deputyId)
        {
            var fromDate = ConvertFromUnixTimestamp(initialDateStamp).Date;
            var toDate = fromDate.AddDays(totalDays);

            var vr = new VacationSchedule
            {
                FromDate = fromDate,
                ResourceId = resourceId,
                ToDate = toDate,
                DeputyId = deputyId
            };

            _vacationScheduleRepository.Save(vr);

            return null;
        }

        #endregion

    }
}
